package com.sduept.nwld.mobile.rest;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sduept.bigdata.fault.common.ParamDesc;
import com.sduept.bigdata.fault.dto.BreakerActionInfoDTO;
import com.sduept.bigdata.fault.manager.BreakerActionAnalysisManager;
import com.sduept.bigdata.fault.model.CTSaturation;
import com.sduept.bigdata.fault.protection.model.ProtectInterruptAlarm;
import com.sduept.bigdata.fault.protection.model.ProtectionActionInfoDTO;
import com.sduept.bigdata.fault.protection.service.ProtectionActionQueryManager;
import com.sduept.core.ParamManager;
import com.sduept.core.dao.SuperDAO;
import com.sduept.core.entity.SystemParameter;
import com.sduept.message.entity.AlarmMessage;
import com.sduept.message.entity.AlarmMessageCheck;
import com.sduept.message.manager.AlarmMessageCheckManager;
import com.sduept.message.manager.AlarmMessageManager;
import com.sduept.nwld.mobile.manager.MobileUtil;
import com.sduept.nwld.mobile.manager.alarm.AlarmQueryManager;
import com.sduept.utils.DateUtil;

/**
 * 异常告警
 *
 */
@RestController
@RequestMapping("/alarm/")
public class ExceptionAlarmService {
	@Autowired
	private SuperDAO dao;
//	@Autowired
//	private RiskAlarmMessageQueryManager ram;
//	@Autowired
//	private CtsaturatedQueryManager ct;
//	@Autowired
//	private BreakerActionAnalysisManager baam;
//	@Autowired
//	private ProtectionActionQueryManager paqm;
//	@Autowired
//	private ProtectDeviceAlarmQueryManager pdac;
	@Autowired
	private AlarmQueryManager aqm; 
	@Autowired
	private BreakerActionAnalysisManager baam;
	@Autowired
	private ProtectionActionQueryManager paqm;
	@Autowired
	private AlarmMessageCheckManager amc;
	@Autowired
	private AlarmMessageManager am;
	@Autowired
	private ParamManager paramCache;
	@Inject
	private MobileUtil mobileUtil;//SQL注入检测类
	/**
	 * 获取所有告警信息
	 * */

	@GetMapping("/getAlarmMsgs")
	public String getAlarmMsgs() {
		//一次设备告警类型 todo springboot 测试
		List<SystemParameter> list = paramCache.listParamsByPid(ParamDesc.GROUP_NWLD_PRIMARY_RISK_MESSAGE);
		Set<String> primaryMsgTypes = list.stream().map(e -> e.getId()).collect(Collectors.toSet());
		List<AlarmMessage> mess1 = am.findAlarmByMsgTypes(primaryMsgTypes);
		List<SystemParameter> secondList = paramCache.listParamsByPid(ParamDesc.GROUP_NWLD_SECONDARY_RISK_MESSAGE);
		Set<String> secondaryMsgTypes = secondList.stream().map(e -> e.getId()).collect(Collectors.toSet());

		List<AlarmMessage> mess2 = am.findAlarmByMsgTypes(secondaryMsgTypes);
		Map<String, List<Map<String, String>>> alarms = new HashMap<>();
		Set<SystemParameter> pps =  getAppAlarmTypes();
		for (SystemParameter p : pps) {
			List<Map<String, String>> as = new ArrayList<>();
			alarms.put(p.getName(), as);
		}
		alarms = initAlarmMesg(mess1, alarms,pps);
		alarms = initAlarmMesg(mess2, alarms,pps);
		return JSONObject.parseObject(JSON.toJSONString(alarms)).toString();
	}
	
	/**
	 * 根据类型、时间、站名查询
	 * @param msgType
	 * @param dateTime
	 * @param stationName
	 * @return
	 */

	@GetMapping("/findAlarmMsgs/{param}")
	public String findAlarmMsgs(@PathVariable("param") String param){
		JSONObject jso=JSONObject.parseObject(param);
		String msgType=jso.getString("msgType");
		String startTime=jso.getString("startTime");
		String endTime=jso.getString("endTime");
		String stationName=jso.getString("stationName");
		try {
			msgType = mobileUtil.SQLInjectCheck(msgType);
			startTime = mobileUtil.SQLInjectCheck(startTime);
			endTime = mobileUtil.SQLInjectCheck(endTime);
			stationName = mobileUtil.SQLInjectCheck(stationName);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		Date start = DateUtil.getDateByString(startTime, DateUtil.pattern_ymd);
		Date end = DateUtil.getDateByString(endTime, DateUtil.pattern_ymd);
		List<AlarmMessage> mess = am.findAlarmByTypeStationDate(msgType, stationName, start, end);
		Map<String, List<Map<String, String>>> alarms = new HashMap<>();
		Set<SystemParameter> pps =  getAppAlarmTypes();
		alarms = initAlarmMesg(mess, alarms, pps);
		
		return JSONObject.parseObject(JSON.toJSONString(alarms)).toString();
	}
	
	
	private Map<String, List<Map<String, String>>> initAlarmMesg(
			List<AlarmMessage> mess,
			Map<String, List<Map<String, String>>> alarms,Set<SystemParameter> pps) {
		
		for (AlarmMessage m : mess) {
			String msgType=m.getMsgType();
			SystemParameter p = paramCache.get(m.getMsgType());
			if(!pps.contains(p)) {
				continue;
			}
			String name = paramCache.get(m.getMsgType())
					.getName();
			List<Map<String, String>> as = alarms.get(name);
			if (as == null) {
				as = new ArrayList<>();
				alarms.put(name, as);
			}
			Map<String, String> map = new HashMap<String, String>();
			map.put("content", m.getContent());
			map.put("createTime", m.getCreateTime().toString());
			map.put("source", m.getSource());
			map.put("msgType", msgType);
			map.put("msgId", m.getId());
			/*if ("bhxyyc".equals(m.getMsgType())) {
				// 保护响应异常需要lineId和faultTime
				AffectedObject ao = ram.getAffectedObject(m.getMsgType(),
						m.getSource());
				if (ao != null) {
					map.put("lineId", ao.getObjectId());
					map.put("faultTime", ao.getFaultTime());
				} else {
					map.put("lineId", "");
					map.put("faultTime", "");
				}
			}*/
			//处理情况
			AlarmMessageCheck check=amc.getAlarmMessageCheckByMsgId(m.getId());
			if(null!=check) {
				if(check.getIsChecked()) {
					map.put("checkMsg", "已确认");
				}else{
					map.put("checkMsg", "待处理");
				}
			}else{
				map.put("checkMsg", "待处理");
			}
			as.add(map);
		}
		return alarms;
	}
	

	@GetMapping("/getAllAlarmType")
	public String getAllAlarmType(){
		//app客户端推送的消息类型，需要用参数配置，有些类型算法还不成熟
		JSONObject jso = new JSONObject();
		Set<SystemParameter> pps =  getAppAlarmTypes();
//		Set<String> primKeySet = pCache.getMap().get(ParamDesc.GROUP_NWLD_PRIMARY_RISK).keySet();
//		Set<String> secKeySet = pCache.getMap().get(ParamDesc.GROUP_NWLD_SECONDARY_RISK).keySet();
		for(SystemParameter p : pps){
			jso.put(p.getId(), p.getName());
		}
		
		return jso.toJSONString();
	}
	
	private Set<SystemParameter> getAppAlarmTypes(){
		Set<SystemParameter> rtns = new HashSet<>();
		String pushmsgs = paramCache.get(ParamDesc.MOBILE_APP_PUSH_ALARMS).getValue();
		if(StringUtils.isNoneEmpty(pushmsgs)) {
			String[] ids = pushmsgs.split(",");
			for(int i = 0; i < ids.length; i++){
				rtns.add(paramCache.get(ids[i]));
			}
		}
		return rtns;
	}
	

	/**
	 * 根据sourceId获取保护装置异常详情
	 * 
	 * @param sourceId
	 * */

	@GetMapping("/getProtectDevice/{sourceId}/{msgId}")
	public String getProtectDevice(@PathVariable("sourceId") String sourceId,@PathVariable("msgId") String msgId) {
		JSONObject jso=new JSONObject();
		/*List<ProtectDeviceAlarm> protectDeviceList = pdac
				.getProtectDeviceAlarmById(sourceId);
		ProtectDeviceAlarm protectDevice = null;
		if (protectDeviceList.size() > 0) {
			protectDevice = protectDeviceList.get(0);
		}*/
		try {
			sourceId = mobileUtil.SQLInjectCheck(sourceId);
			msgId = mobileUtil.SQLInjectCheck(msgId);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		AlarmMessageCheck check=amc.getAlarmMessageCheckByMsgId(msgId);
		if(null==check) {
			check=new AlarmMessageCheck();
		}
		jso.put("check", check);
		return jso.toString();
	}

	
	
	
	
	/**
	 * 根据sourceId获取保护通道异常详情
	 * 
	 * @param sourceId
	 * */

	@GetMapping("/getChannelExp/{sourceId}/{msgId}")
	public String getChannelExp(@PathVariable("sourceId") String sourceId,@PathVariable("msgId") String msgId) {
		try {
			sourceId = mobileUtil.SQLInjectCheck(sourceId);
			msgId = mobileUtil.SQLInjectCheck(msgId);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		JSONObject jso=new JSONObject();
		List<ProtectInterruptAlarm> protectChannelList=new ArrayList<>();
		ProtectInterruptAlarm alarm=dao.findById(sourceId, ProtectInterruptAlarm.class);
		AlarmMessageCheck check=amc.getAlarmMessageCheckByMsgId(msgId);
		if(alarm!=null){
			Date start = alarm.getEventStart();
			Date end = new Date(alarm.getEventStart().getTime()+86400000);
			protectChannelList=aqm.getProtectInterruptAlarmByProtectIdAndDate(alarm.getProtectId(), start, end);
		}
		if(null==check) {
			check=new AlarmMessageCheck();
		}
		jso.put("detail", protectChannelList);
		jso.put("check", check);
		return jso.toString();
	}

	
	
	
	
	/**
	 * 根据sourceId获取ct饱和详情
	 * 
	 * @param sourceId
	 * */

	@GetMapping("/getCTSA/{sourceId}/{msgId}")
	public String getCTSA(@PathVariable("sourceId") String sourceId,@PathVariable("msgId") String msgId) {
		try {
			sourceId = mobileUtil.SQLInjectCheck(sourceId);
			msgId = mobileUtil.SQLInjectCheck(msgId);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		JSONObject jso=new JSONObject();
		CTSaturation ctModel = null;
		List<CTSaturation> ctModels = aqm.getCTSaturationById(sourceId);
		if(ctModels.size()>0){
			ctModel=ctModels.get(0);
		}
		AlarmMessageCheck check=amc.getAlarmMessageCheckByMsgId(msgId);
		if(null==check) {
			check=new AlarmMessageCheck();
		}
		jso.put("detail", ctModel);
		jso.put("check", check);
		return jso.toString();
	}
	/**
	 * 根据sourceId获取保护动作异常详情
	 * 
	 * @param sourceId
	 * */

	@GetMapping("/getProtectActInfo/{sourceId}/{msgId}")
	public String getProtectActInfo(@PathVariable("sourceId") String sourceId,@PathVariable("msgId") String msgId) {
		try {
			sourceId = mobileUtil.SQLInjectCheck(sourceId);
			msgId = mobileUtil.SQLInjectCheck(msgId);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		JSONObject jso=new JSONObject();
//		ProtectionActionInfo protectAct=aqm.getProtectionActionInfoById(sourceId);
		
		ProtectionActionInfoDTO paDTO=null;
		List<ProtectionActionInfoDTO> protectActs=paqm.getProtectionActionTimeDtoById(sourceId);
		if(protectActs.size()>0){
			paDTO = protectActs.get(0);
		}
		AlarmMessageCheck check=amc.getAlarmMessageCheckByMsgId(msgId);
		if(null==check) {
			check=new AlarmMessageCheck();
		}
		jso.put("detail", paDTO);
		jso.put("check", check);
		return jso.toString();
	}


	/**
	 * 根据sourceId获取断路器动作异常详情
	 * 
	 * @param sourceId
	 * */

	@GetMapping("/getBreakerExp/{sourceId}/{msgId}")
	public String getBreakerExp(@PathVariable("sourceId") String sourceId,@PathVariable("msgId") String msgId) {
		try {
			sourceId = mobileUtil.SQLInjectCheck(sourceId);
			msgId = mobileUtil.SQLInjectCheck(msgId);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		JSONObject jso=new JSONObject();
//		BreakerActionInfo breakerAct = aqm.getBreakerActionInfoById(sourceId);
        //TODO:总调移动端后台，若单独使用，需要修改总调后台程序AlarmQueryManager中的getBreakerActionInfoById（）	
		BreakerActionInfoDTO breakerAct = baam.getBreakerActionInfoById(sourceId);
		
		AlarmMessageCheck check=amc.getAlarmMessageCheckByMsgId(msgId);
		if(null==check) {
			check=new AlarmMessageCheck();
		}
		jso.put("detail", breakerAct);
		jso.put("check", check);
		return jso.toString();
	}
//
	/**
	 * 获取断路器波形数据
	 * */

	@GetMapping("/getBreakerWaveData/{fileId}/{breakerId}/{phase}")
	public String getBreakerWaveData(@PathVariable("fileId") String fileId,
			@PathVariable("breakerId") String breakerId,
			@PathVariable("phase") String phase) {
		try {
			fileId = mobileUtil.SQLInjectCheck(fileId);
			breakerId = mobileUtil.SQLInjectCheck(breakerId);
			phase = mobileUtil.SQLInjectCheck(phase);
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		if (!"null".equals(fileId) && !"null".equals(breakerId)) {
			List<?> waveList = dao
					.nativeQuery("select fault_file_id,breaker_id from t_lbtz_breaker_wave_data");
			boolean checkId = false;
			for (Object obj : waveList) {

				Object[] objs = (Object[]) obj;
				if (objs[0].toString().equalsIgnoreCase(fileId)
						&& objs[1].toString().equals(breakerId)) {// id在数据库中有
					checkId = true;
				}
			}
			if (!checkId) {
				return "";
			}
		} else {
			return "";
		}
		if (!phase.matches("[A-Ca-c]*")) {
			return "";
		}
		double[][] posWS = aqm.getPostFaultWaveletData(fileId, breakerId,
				phase);
		double[][] preWS = aqm
				.getPreFaultWaveletData(fileId, breakerId, phase);
		JSONObject jso = new JSONObject();
		JSONArray preRtn = new JSONArray();
		for (double[] d : preWS) {
			preRtn.add(d);
		}
		jso.put("preFault", preRtn);
		JSONArray postRtn = new JSONArray();
		for (double[] d : posWS) {
			postRtn.add(d);
		}
		jso.put("postFault", postRtn);
		// 获取保护最早动作时间
		String sqlStr = "select min(distance_0_moments_time) from t_protection_action_info where fault_file_id =? and phase=?";
		Object[] params = new Object[2];
		params[0] = fileId;
		params[1] = phase;
		List<?> objs = dao.nativeQuery(sqlStr, params);
		Object os = (Object) objs.get(0);
		jso.put("protectMinAct", os.toString());
		return jso.toString();
	}
}
